package cn.ly;

import cn.ly.lock.Lock;
import cn.ly.lock.ZkLock;

import java.util.concurrent.CountDownLatch;

/**
 * 测试wo们实现的Zk分布式锁
 */
public class TestLock {
    //全局共享资源：count
    static int count = 0;
    //线程数：记得修改zk配置文件：maxClientCnxns=60。表示Zookeeper中同一ip可以并发的最大连接数。需要调大一些
    static int thread_size = 50;
    //此处的CountDownLatch只是为了在main函数中，等待各个线程执行完毕后，输出结果用
    static CountDownLatch countDownLatch = new CountDownLatch(thread_size);

    public static void main(String[] args) throws InterruptedException {
        for (int i = 0; i < thread_size; i++) {
            new Thread(new MyRunnable()).start();
        }
        countDownLatch.await();
        System.out.println(">>>>>>>result:" + count);
    }

    //    static Lock lock = new ZkLock2(); //测试：所有线程共用一把锁测试
    //线程任务
    static class MyRunnable implements Runnable {
        //我们的Zookeeper分布式锁，每个线程中都可以独自单独持有一个ZkLock（即内部new一个ZkClient去操作Zookeeper的节点）
        // 区别于JDK的lock、sync对象锁它们都是全局的一个锁对象。然后所有线程去使用这个全局锁，进行排队上锁、释放锁
        //原因：其实方式一是可以让所有线程共用一个ZkLock的，只是关闭锁的时候不要将zkClient.close()关闭辽
        //      方式二不能共用的原因是：ZkLock2中有俩全局变量：currentPath、beforePath。改成线程私有也是可以共享同一个zkClient客户端的

        Lock lock = new ZkLock();   //每个线程单独new一把Zk锁
        public void run() {
            lock.getLock();
            System.out.println(">>>>>>>抢到锁");
            try {
                count = count + 100;
                Thread.sleep(300);
                count = count - 90;
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                System.out.println(">>>>>>准备释放锁");
                lock.unLock();
                countDownLatch.countDown();
            }
        }
    }
}
